package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.heima.common.dtos.PageResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;

import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.model.media.dtos.WmNewsPageReqDto;
import com.heima.wemedia.entity.WmMaterial;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmMaterialService;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsMaterialService;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.heima.common.constants.message.WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    /**
     * 分页查询 自媒体文章信息
     *
     * @param wmNewsPageReqDto
     * @return
     */
    @Override
    public PageResult<WmNews> findByPage(WmNewsPageReqDto wmNewsPageReqDto) {
//        获取用户信息
        Integer userId = UserThreadLocalUtils.getUserId();
        log.info("当前用户id={}", userId);
        if (userId == null) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
//        构造分页条件
        Page<WmNews> page = new Page<>(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize());
//        构造查询条件
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
//        设置用户id条件
        queryWrapper.lambda().eq(WmNews::getWmUserId, userId);
//        设置关键词
        if (StringUtils.isNotBlank(wmNewsPageReqDto.getKeyword())) {
            queryWrapper.lambda().like(WmNews::getTitle, wmNewsPageReqDto.getKeyword());
        }
//        设置状态 不为空，不等于-1 时查询
        if (wmNewsPageReqDto.getStatus() != null && wmNewsPageReqDto.getStatus() != -1) {
            if (wmNewsPageReqDto.getStatus() == 1) {
//             待审核包括 1-已提交待审核，3-待人工审核
                queryWrapper.lambda().in(WmNews::getStatus, new Integer[]{1, 3});
            } else if (wmNewsPageReqDto.getStatus() == 4) {
//             审核通过 包括4-人工审核通过  ,待发布 8 审核通过（待发布） 9 已发布
                queryWrapper.lambda().in(WmNews::getStatus, new Integer[]{4, 8, 9});
            } else {
//                查询 草稿或 审核不通过
                queryWrapper.lambda().eq(WmNews::getStatus, wmNewsPageReqDto.getStatus());
            }
        }
//        设置频道id
        if (wmNewsPageReqDto.getChannelId() != null) {
            queryWrapper.lambda().eq(WmNews::getChannelId, wmNewsPageReqDto.getChannelId());
        }
//        设置发布时间段查询
        if (wmNewsPageReqDto.getBeginPubDate() != null) {
            queryWrapper.lambda().ge(WmNews::getPublishTime, wmNewsPageReqDto.getBeginPubDate());
        }
        if (wmNewsPageReqDto.getEndPubDate() != null) {
            queryWrapper.lambda().le(WmNews::getPublishTime, wmNewsPageReqDto.getEndPubDate());
        }
//        分页查询
        IPage<WmNews> wmNewsIPage = this.page(page, queryWrapper);
//        构造分页返回结果
        PageResult<WmNews> pageResult = new PageResult<>(wmNewsPageReqDto.getPage(),
                wmNewsPageReqDto.getSize(),
                wmNewsIPage.getTotal(),
                wmNewsIPage.getRecords());
        return pageResult;
    }

    @Autowired
    private WmNewsMaterialService wmNewsMaterialService;
    @Autowired
    private WmMaterialService wmMaterialService;

    @Autowired
    private WmNewsAuditService wmNewsAuditService;

    @Autowired
    private KafkaTemplate kafkaTemplate;
    /**
     * 保存、修改、发布自媒体文章
     *
     * @param wmNewsDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveNews(WmNewsDto wmNewsDto) {
//        判断参数,如果标题、内容为空返回错误
        if (wmNewsDto == null ||
                StringUtils.isBlank(wmNewsDto.getTitle()) ||
                StringUtils.isBlank(wmNewsDto.getContent())) {
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID, "参数错误！");
        }
//        获取用户信息
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null || userId == 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
//      对象转换
        WmNews wmNews = BeanHelper.copyProperties(wmNewsDto, WmNews.class);
        if (wmNews.getId() == null) {
//            新增操作
            wmNews.setCreatedTime(new Date());
            wmNews.setWmUserId(userId);
        }
        if (!wmNewsDto.getDraft()) {
//          如果是提交需要记录提交时间
            wmNews.setSubmitedTime(new Date());
        }
        if (!CollectionUtils.isEmpty(wmNewsDto.getImages())) {
//            处理封面图片地址,多个地址使用，进行分割
            String images = wmNewsDto.getImages().stream().collect(Collectors.joining(","));
            wmNews.setImages(images);
        }
//        保存文章表,新增或修改
        this.saveOrUpdate(wmNews);
//        文章表和素材表是多对多关系，如果是修改文章表，需要先把中间表信息删除
        if (wmNewsDto.getId() != null) {
            wmNewsMaterialService.deleteByNewsId(wmNews.getId());
        }
//        文章内容 类型转换，把json数据转map对象
        List<Map<String, Object>> contents = JsonUtils.nativeRead(wmNewsDto.getContent(), new TypeReference<List<Map<String, Object>>>() {
        });
//        从文章内容中，获取素材id集合
        List<Integer> contentMaterialIds = getMaterialIdsByContent(contents);
        log.info("#####contentMaterialIds 1 is {}", contentMaterialIds);
//        保存文章内容和素材表关联，0 - 内容引用
        //        保存素材和文章的关系
        if (!CollectionUtils.isEmpty(contentMaterialIds)) {
            wmNewsMaterialService.saveInfoBatch(contentMaterialIds, wmNews.getId(), 0);
        }
        if (!CollectionUtils.isEmpty(wmNewsDto.getImages())) {
//        根据封面中图片url，找到素材的id
            List<Integer> imageMaterialIds = getMaterialIdsByUrls(wmNewsDto.getImages(), userId);
            log.info("#####imageMaterialIds 2 is {}", imageMaterialIds);
//        保存文章封面 和 素材的关联 ，1- 封面内容
            wmNewsMaterialService.saveInfoBatch(imageMaterialIds, wmNews.getId(), 1);
        }

        //       如果是提交审核 异步审核文章内容
        if (!wmNewsDto.getDraft()) {
            wmNewsAuditService.auditWmNews(wmNews.getId());
        }

    }

    //自媒体文章上下架
    @Override
    public void downOrUp(WmNewsDto dto) {
        //1. 获取当前登录用户的id
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null || userId == 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2. 设置查询条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getId, dto.getId()).eq(WmNews::getWmUserId, userId);
        //3. 根据查询条件获取当前用户
        WmNews wmNews = getOne(queryWrapper);
        //4. 判断当前用户是否为空
        if (wmNews == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        if (wmNews.getStatus() != 9) {
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getEnable().equals(wmNews.getEnable())) {
            //4.1 前后端传输数据一致，啥也不用做
            return;
        }
        //5. 更新自媒体文章，上下架状态
        LambdaUpdateWrapper<WmNews> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(WmNews::getEnable, dto.getEnable()).eq(WmNews::getId, dto.getId());
        boolean b = update(updateWrapper);
        if (!b) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
        //6. 构造消息内容
        Map<String, Long> map = new HashMap<>();
        map.put("articleId", dto.getArticleId());
        map.put("enable", dto.getEnable() ? 1L : 0L);
        //7. 成功后发送kafka消息
        kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC,JsonUtils.toString(map));
    }

    /**
     * 获取封面图片的素材id集合
     *
     * @param images
     * @return
     */
    private List<Integer> getMaterialIdsByUrls(List<String> images, Integer userId) {
        QueryWrapper<WmMaterial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmMaterial::getUserId, userId).in(WmMaterial::getUrl, images);
        List<WmMaterial> wmMaterialList = wmMaterialService.list(queryWrapper);
        if (CollectionUtils.isEmpty(wmMaterialList)) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        List<Integer> ids = wmMaterialList.stream().map(WmMaterial::getId).collect(Collectors.toList());
        return ids;
    }

    /**
     * 获取文章内容中的素材id集合
     *
     * @param contentList
     * @return
     */
    private List<Integer> getMaterialIdsByContent(List<Map<String, Object>> contentList) {
        List<Integer> materialIds = new ArrayList<>();
        for (Map<String, Object> map : contentList) {
            String type = (String) map.get("type");
            if (type.equals("image")) {
                Integer materialId = (Integer) map.get("id");
                materialIds.add(materialId);
            }
        }
        return materialIds;
    }
}